package com.tim.shadow.lib.util;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

/**
 * JSON 简便解析工具类
 * 
 * @version 1.0.0
 * @author poper xuting90@gmail.com <br>
 */
public class TJSONParse {
	// private static final boolean needChecked = true;

	private static boolean hasNamedFeild(Field[] fields, String name) {
		for (Field f : fields) {
			if (f.getName().equals(name))
				return true;
		}
		return false;
	}

	/**
	 * 只能解析纯属性的{@code JSONObject}的字段
	 * 
	 * @param objClass
	 *            需要被解析成的类型
	 * @param jsonStr
	 *            JSON对应的字符串
	 * @return T 返回的类型，与需要被解析的类型有关({@link objClass})
	 */
	public static <T extends Object> T getObj(Class<T> objClass, String jsonStr) {
		T objBean = null;
		try {
			objBean = objClass.newInstance();
			JSONObject jsonObj = new JSONObject(jsonStr);
			Iterator<?> keys = jsonObj.keys();
			Field[] fields = objClass.getDeclaredFields();
			while (keys.hasNext()) {
				String key = keys.next().toString();
				String value = jsonObj.getString(key);

				Object valueObj = jsonObj.get(key);
				if (valueObj instanceof JSONArray) {
					System.out.println("JSONArray");
				}
				if (valueObj instanceof JSONObject) {
					System.out.println("JSONObject");
				}
				if (valueObj instanceof String) {
					System.out.println("String");
				}

				System.out.println(key + ":" + value);
				Field field = null;
				if (hasNamedFeild(fields, key)) {
					field = objClass.getDeclaredField(key);
					field.setAccessible(true);
					field.set(objBean, value);
				} else {
					Log.e("t_log", "您的实体类缺少字段：\n" + key);
				}
			}
		} catch (InstantiationException e) {
			Log.e("t_log", "请检查Bean类构造方法");
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			Log.e("t_log", "不能给对应属性赋值，请检测属性的可见性");
			e.printStackTrace();
		} catch (JSONException e) {
			Log.e("t_log", "请检测对应的Json是否为基础属性的JsonObject");
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			Log.e("t_log", "检测到您的实体类里面缺少对应字段，请修改您的实体类");
			e.printStackTrace();
		}
		return objBean;
	}

	/**
	 * 只能解析纯对象{@code JSONArray}的字段
	 * 
	 * @param objClass
	 *            需要被解析成的类型
	 * @param jsonStr
	 *            JSON对应的字符串
	 * @return T 返回的类型，与需要被解析的类型有关({@link objClass})
	 * @return 返回的对应类型的List
	 */
	public static <T extends Object> List<T> getList(Class<T> objClass,
			String jsonStr) {
		List<T> objlist = new ArrayList<T>();
		JSONArray jsonArray;
		try {
			jsonArray = new JSONArray(jsonStr);
			int len = jsonArray.length();
			for (int i = 0; i < len; i++) {
				JSONObject jsonObj = jsonArray.getJSONObject(i);
				T objBean = getObj(objClass, jsonObj.toString());
				objlist.add(objBean);
			}
		} catch (JSONException e) {
			Log.e("t_log", "请检测对应的Json是否为JsonArray");
			e.printStackTrace();
		}
		return objlist;
	}

	/**
	 * 只能解析纯对象{@code JSONArray}的字段
	 * 
	 * @param objClass
	 *            需要被解析成的类型
	 * @param jsonStr
	 *            JSON对应的字符串
	 * @param listClass
	 *            子属性对应的类型
	 * @return T 返回的类型，与需要被解析的类型有关({@link objClass})
	 */
	public static <T, M extends Object> T getFieldObj(Class<T> objClass,
			String jsonStr, Class<M> listClass) {
		int objNum = 0;// 用来计算第一层所包含的对象的个数；
		T objFieldobj = null;
		try {
			objFieldobj = objClass.newInstance();
			JSONObject obj = null;
			Field[] fields = objClass.getDeclaredFields();
			obj = new JSONObject(jsonStr);
			Iterator<?> keys = obj.keys();
			while (keys.hasNext()) {
				String key = keys.next().toString();
				Object valueObj = obj.get(key);
				if (valueObj instanceof JSONArray) {// 如果是数组
					objNum++;
					if (hasNamedFeild(fields, key)) {
						Field field = objClass.getDeclaredField(key);
						Type type = ((ParameterizedType) field.getGenericType())
								.getActualTypeArguments()[0];
						if (type == listClass) {// Json对象的类型与传进来的相同
							List<M> beanList = getList(listClass,
									valueObj.toString());
							field.setAccessible(true);
							field.set(objFieldobj, beanList);
						} else {
							Log.e("t_log", "请检查 子JsonObject 是否与 子属性 对应" + key);
						}
					} else {
						Log.e("t_log", "您的实体类缺少字段：\n" + key);
					}
				} else if (valueObj instanceof JSONObject) {// 如果是对象
					objNum++;
					if (hasNamedFeild(fields, key)) {
						Field field = objClass.getDeclaredField(key);
						Class<?> type = field.getType();
						if (type == listClass) {// Json对象的类型与传进来的相同
							M beanObj = getObj(listClass, valueObj.toString());
							field.setAccessible(true);
							field.set(objFieldobj, beanObj);
						} else {
							Log.e("t_log", "请检查 子JsonObject 是否与 子属性 对应" + key);
						}
					} else {
						Log.e("t_log", "您的实体类缺少字段：\n" + key);
					}
				} else {// 如果是其他
					if (hasNamedFeild(fields, key)) {
						Field field = objClass.getDeclaredField(key);
						field.setAccessible(true);
						field.set(objFieldobj, valueObj.toString());
					} else {
						Log.e("t_log", "您的实体类缺少字段：\n" + key);
					}
				}
			}

		} catch (JSONException e) {
			Log.e("t_log", "请检测对应的Json是否为JsonArray");
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		if (objNum == 0) {
			// 这只是一个警告
			Log.w("t_log", objNum + ":"
					+ "警告（可以忽略，可以优化是用getObj）：请检查您的Json中是否包含了所对应的实体类");
		} else if (objNum > 1) {
			Log.e("t_log", objNum + ":" + "检查您的Json中是否只包含了一种所对应的实体类");
		} else {
			Log.i("t_log", objNum + ":" + "恭喜（可以忽略）：检查您的Json中只包含了一种所对应的实体类");
		}

		return objFieldobj;
	}

	public static Object getJsonOBJ(Class<?> objClass, String jsonStr) {
		Object resultObj = null;
		JSONObject jsonObj = null;
		try {
			resultObj = Class.forName(objClass.getCanonicalName())
					.newInstance();
			jsonObj = new JSONObject(jsonStr);
			Iterator<?> keys = jsonObj.keys();
			while (keys.hasNext()) {
				String key = keys.next().toString();
				Object value = jsonObj.get(key);
				if (value instanceof JSONObject) {
					System.out.println("jsonObj");
					Field field = objClass.getDeclaredField(key);
					Class<?> sonClass = field.getType();
					String sonJsonStr = value.toString();
					field.setAccessible(true);
					field.set(resultObj, getJsonOBJ(sonClass, sonJsonStr));
				} else if (value instanceof JSONArray) {
					JSONArray array = (JSONArray) value;
					Field field = objClass.getDeclaredField(key);
					Type type = ((ParameterizedType) field.getGenericType())
							.getActualTypeArguments()[0];
					List<Object> list = new ArrayList<Object>();
					int length = array.length();
					for (int i = 0; i < length; i++) {
						Class<? extends Object> sonClass = (Class<?>) type;
						JSONObject sonObj = array.getJSONObject(i);
						list.add(getJsonOBJ(sonClass, sonObj.toString()));
					}
					field.setAccessible(true);
					field.set(resultObj, list);
				} else {
					System.out.println(key);
					Field field = objClass.getDeclaredField(key);
					field.setAccessible(true);
					field.set(resultObj, value.toString());
				}
			}
		} catch (InstantiationException e) {
			Log.e("t_log", "请检查Bean类构造方法");
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			Log.e("t_log", "不能给对应属性赋值，请检测属性的可见性");
			e.printStackTrace();
		} catch (JSONException e) {
			Log.e("t_log", "请检测对应的Json是否为基础属性的JsonObject");
			e.printStackTrace();
		} catch (NoSuchFieldException e) {
			Log.e("t_log", "检测到您的实体类里面缺少对应字段，请修改您的实体类");
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
		System.out.println(resultObj.toString());
		return resultObj;
	}

}
